//
//  YZRecordManager.m
//  CocoaAsyncSocketClient
//
//  Created by lixiaoyi on 2018/6/22.
//  Copyright © 2018年 lixiaoyi. All rights reserved.
//

#import "YZRecordManager.h"
#import "YZFileTool.h"
#import <UIKit/UIKit.h>

#define kChildPath @"Chat/Recorder"
#define kRecorderType @".aac"
#define kMinRecordDuration 1.0


@interface YZRecordManager() {
    NSDate *startDate;
    NSDate *endDate;
}

@property (nonatomic ,strong) NSDictionary *recordSetting;
@property (nonatomic ,assign) BOOL isPaused;
@end

@implementation YZRecordManager


static YZRecordManager *manager = nil;

+ (YZRecordManager *)shareManager {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[YZRecordManager alloc] init];
    });
    
    return manager;
}

- (void)startRecordWithFileName:(NSString *)fileName completion:(YZRecordError)error {
    NSError *err = nil;
    if (![[YZRecordManager shareManager] canRecord]) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"无法录音" message:@"请在iPhone的“设置-隐私-麦克风”选项中，允许iCom访问你的手机麦克风。" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
        
        if (error) {
            err = [NSError errorWithDomain:NSLocalizedString(@"error", @"没权限") code:122 userInfo:nil];
            error(err);
        }
        
        return;
    }
    
    if ([_recorder isRecording]) {
        [_recorder stop];
        [self cancelCurrentRecording];
        return;
    } else {
        NSString *aacFilePath = [self recorderPathWithFileName:fileName];
        NSURL *aacUrl = [[NSURL alloc] initFileURLWithPath:aacFilePath];
        
        // 实例化录音
        AVAudioSession *session = [AVAudioSession sharedInstance];
        NSError *setCategoryError = nil;
        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&setCategoryError];
        if (setCategoryError) {
            NSLog(@"%@",[setCategoryError description]);
        }
        
        _recorder = [[AVAudioRecorder alloc] initWithURL:aacUrl settings:self.recordSetting error:&err];
        _recorder.meteringEnabled = YES;
        if (!_recorder || err) {
            _recorder = nil;
            if (err) {
                err = [NSError errorWithDomain:NSLocalizedString(@"error.initRecorderFail", @"Failed to initialize AVAudioRecorder") code:123 userInfo:nil];
                error(err);
            }
            
            return;
        }
        
        startDate = [NSDate date];
        _recorder.meteringEnabled = YES;
        _recorder.delegate = self;
        [_recorder record];
        
        if (error) {
            error(err);
        }
    }
}

- (BOOL)canRecord {
    __block BOOL bCanRecord = YES;
    if ([[[UIDevice currentDevice] systemVersion] compare:@"7.0"] != NSOrderedAscending) {
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        if ([audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
            [audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
                bCanRecord = granted;
            }];
        };
    }
    
    return bCanRecord;
}

- (void)pauseRecord{
    [self.recorder pause];
    self.isPaused = YES;
}
- (void)resumeRecord{
    [self.recorder record];
    self.isPaused = NO;
}

- (void)stopRecordCompletion:(YZRecordCompletion)completion {
    endDate = [NSDate date];
    if ([_recorder isRecording] || _isPaused) {
        _isPaused = NO;
        if ([endDate timeIntervalSinceDate:startDate] <  [self recordMinDuration]) {
            if (completion) {
                completion(shortRecord);
            }
            [self.recorder stop];
            [self cancelCurrentRecording];
            sleep(1.0);
            NSLog(@"record time duration is too short");
            return;
        }
        
        self.recordFinish = completion;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self.recorder stop];
            NSLog(@"record time duration : %f",[endDate timeIntervalSinceDate:startDate]);
        });
    }
}

- (NSString *)recordMainPath {
    return [YZFileTool createPathWithChildPath:kChildPath];
}

- (NSString *)recorderPathWithFileName:(NSString *)fileName {
//    NSString *path = [self recordMainPath];
//    return [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",fileName,kRecorderType]];
    
    // NSDocumentDirectory路径
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

    // 当前日期
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"YYYY-MM-dd"];
    NSString *dateFolder = [formatter stringFromDate:date];
    path = [path stringByAppendingPathComponent:dateFolder];
    if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@",fileName,kRecorderType]];;
}

- (void)cancelCurrentRecording {
    _recorder.delegate = nil;
    if (_recorder.isRecording) {
        [_recorder stop];
    }
    
    _recorder = nil;
    self.recordFinish = nil;
}

- (NSDictionary *)recordSetting {
    if (!_recordSetting) {
        
        NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
        //设置录音格式
        //    [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
        [dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];
        //设置录音采样率，8000是电话采样率，对于一般录音已经够了
        [dicM setObject:@(8000) forKey:AVSampleRateKey];
        //设置通道,这里采用单声道
        [dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
        //每个采样点位数,分为8、16、24、32
        [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
        //是否使用浮点数采样
        [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
        //....其他设置等
        [dicM setObject:@(AVAudioQualityHigh) forKey:AVEncoderAudioQualityKey];
        
        _recordSetting = [NSDictionary dictionaryWithDictionary:dicM];
    }
    
    return _recordSetting;
}

- (NSString *)receiveVoicePathWithFileKey:(NSString *)fileKey {
    return [self recorderPathWithFileName:fileKey];
}

- (CGFloat)recordMinDuration {
    return  kMinRecordDuration;
}

- (void)removeCurrentRecordFile:(NSString *)fileName {
    [self cancelCurrentRecording];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *path = [self recorderPathWithFileName:fileName];
    BOOL isDirExist = [fileManager fileExistsAtPath:path];
    if (isDirExist) {
        [fileManager removeItemAtPath:path error:nil];
    }
}

#pragma mark - AVAudioRecorderDelegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
                           successfully:(BOOL)flag {
    NSString *recordPath = [[_recorder url] path];
    if (self.recordFinish) {
        if (!flag) {
            recordPath = nil;
        }
        self.recordFinish(recordPath);
    }
    
    _recorder = nil;
    self.recordFinish = nil;
}

/* if an error occurs while encoding it will be reported to the delegate. */
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder
                                   error:(NSError * __nullable)error {
    NSLog(@"audioRecorderEncodeErrorDidOccur");
}

#pragma mark - player
- (void)startPlayRecorder:(NSString *)recorderPath  {
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *error = nil;
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderPath] error:nil];
    self.player.numberOfLoops = 0;
    [self.player prepareToPlay];
    self.player.delegate = self;
    [self.player play];
}

- (void)stopPlayRecorder:(NSString *)recorderPath {
    [self.player stop];
    self.player = nil;
    self.player.delegate = nil;
}

- (void)pause {
    [self.player pause];
}

#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    [self.player stop];
    self.player = nil;
    if (self.playDelegate && [self.playDelegate
                              respondsToSelector:@selector(voiceDidPlayFinished)]) {
        [self.playDelegate voiceDidPlayFinished];
    }
}

// 获取语音时长
- (NSUInteger)durationWithVideo:(NSURL *)voiceUrl{
    
    NSDictionary *opts = [NSDictionary dictionaryWithObject:@(NO) forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:voiceUrl options:opts]; // 初始化视频媒体文件
    NSUInteger second = 0;
    second = urlAsset.duration.value / urlAsset.duration.timescale; // 获取视频总时长,单位秒
    return second;
}

- (NSUInteger)getVideoDuration:(NSURL *)urlPath {
    AVURLAsset *audioAsset = [AVURLAsset assetWithURL:urlPath];
    CMTime durationTime = audioAsset.duration;
    NSInteger resultTime = 0;
    resultTime = CMTimeGetSeconds(durationTime);
    return resultTime;
}

// 因为沙盒主目录会变，这里重新转换一下之前保存的录音文件路径
- (NSString *)changeAudioPath:(NSString *)tempPath {
    // 文件路径
    NSString *voicePath = @"";
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    // 当前日期
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"YYYY-MM-dd"];
    NSString *dateFolder = [formatter stringFromDate:date];
    path = [path stringByAppendingPathComponent:dateFolder];
    // 加上文件名
    path = [path stringByAppendingPathComponent:[tempPath lastPathComponent]];
    voicePath = path;
    return voicePath;
}


@end
